//  Copyright (c) 2012-2013, Jordi Corbilla
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are met:
//
//  - Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//  - Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//  - Neither the name of this library nor the names of its contributors may be
//    used to endorse or promote products derived from this software without
//    specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
//  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//  POSSIBILITY OF SUCH DAMAGE.

unit thundax.Prototype;

interface

uses
  Generics.Collections, Contnrs;

type
  IVehicle = interface
    function Clone() : IVehicle;
    function ToString() : string;
  end;

  TCar = class(TInterfacedObject, IVehicle)
    function Clone() : IVehicle;
    function ToString() : string; override;
  end;

  TTruck = class(TInterfacedObject, IVehicle)
    function Clone() : IVehicle;
    function ToString() : string; override;
  end;

  TBus = class(TInterfacedObject, IVehicle)
    function Clone() : IVehicle;
    function ToString() : string; override;
  end;

  TVan = class(TInterfacedObject, IVehicle)
    function Clone() : IVehicle;
    function ToString() : string; override;
  end;

  TPrototypeFactory = class(TObject)
  private
    FVehicleDictionary : TDictionary<string, IVehicle>;
  public
    constructor Create();
    destructor Destroy(); override;
    function MakeObject(Vehicle : String) : IVehicle;
  end;

implementation

uses
  SysUtils;

{ TBus }

function TBus.Clone: IVehicle;
begin
  Result := TBus.Create;
end;

function TBus.ToString: string;
begin
  Result := 'Bus';
end;

{ TTruck }

function TTruck.Clone: IVehicle;
begin
  Result := TTruck.Create;
end;

function TTruck.ToString: string;
begin
  Result := 'Truck';
end;

{ TCar }

function TCar.Clone: IVehicle;
begin
  Result := TCar.Create;
end;

function TCar.ToString: string;
begin
  Result := 'Car';
end;

{ TPrototypeFactory }

constructor TPrototypeFactory.Create;
begin
  FVehicleDictionary := TDictionary<String,IVehicle>.create;
  FVehicleDictionary.Add('Car', TCar.Create);
  FVehicleDictionary.Add('Truck', TTruck.Create);
  FVehicleDictionary.Add('Bus', TBus.Create);
  FVehicleDictionary.Add('Van', TVan.Create);
end;

destructor TPrototypeFactory.Destroy;
begin
  FreeAndNil(FVehicleDictionary);
  inherited;
end;

function TPrototypeFactory.MakeObject(Vehicle: String): IVehicle;
var
  outVehicle : IVehicle;
begin
  FVehicleDictionary.TryGetValue(Vehicle, outVehicle);
  result := outVehicle.Clone;
end;

{ TVan }

function TVan.Clone: IVehicle;
begin
  Result := TVan.Create;
end;

function TVan.ToString: string;
begin
  Result := 'Van';
end;

end.
